package com.wash.shoes.controller.dy;

import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.annotation.Resource;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.StringUtils;
import com.wash.shoes.common.property.DyProperty;
import com.wash.shoes.domain.dy.model.Code2SessionRequest;
import com.wash.shoes.domain.dy.model.Code2SessionResponse;
import com.wash.shoes.domain.dy.model.EncryptedPhone;
import com.wash.shoes.domain.dy.store.Store;
import com.wash.shoes.domain.dy.util.CbcCoding;
import com.wash.shoes.domain.dy.util.HttpUtil;
import com.wash.shoes.domain.vo.CustomerVo;
import com.wash.shoes.domain.vo.DyUserInfo;
import com.wash.shoes.entity.BrandPo;
import com.wash.shoes.entity.CustomerPo;
import com.wash.shoes.entity.ShopPo;
import com.wash.shoes.exception.WashException;
import com.wash.shoes.service.BrandService;
import com.wash.shoes.service.CustomerService;
import com.wash.shoes.service.ShopService;
import com.wash.shoes.util.HeaderUtil;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;

@Log4j2
@Api(tags = {"抖音-登录等信息"})
@RestController
@RequestMapping("/mobile-api/")
public class LoginDyController {

    @Autowired
    private DyProperty dyProperty;

    @Resource
    private CustomerService customerService;

    @Resource
    private ShopService shopService;
    @Autowired
    private BrandService brandService;

    /**
     * 小程序利用code2session登录获取openid返回
     *
     * @return
     * @throws IOException
     */
    @ApiOperation("小程序利用code2session登录获取openid返回")
    @PostMapping(value = "/apps/login", consumes = MediaType.APPLICATION_JSON_VALUE)
    public R<CustomerPo> handle(@RequestBody Code2SessionRequest code2SessionRequest) throws IOException {
        // 请求体初始化pb结构
        code2SessionRequest.setAppid(dyProperty.getAppId());
        code2SessionRequest.setSecret(dyProperty.getAppSecret());
        code2SessionRequest.setAnonymousCode(null);
        // 正式地址：https://developer.toutiao.com/api/apps/v2/jscode2session
        // 沙盒地址：https://open-sandbox.douyin.com/api/apps/v2/jscode2session
        String domain = "developer.toutiao.com";
        if (dyProperty.getIsSandBox().equals("1")) {
            domain = "open-sandbox.douyin.com";
        }
        String code2SessionPath = "/api/apps/v2/jscode2session";
        Code2SessionResponse response = HttpUtil.HttpPost(code2SessionPath,
            JSONObject.toJSONString(code2SessionRequest), "https", domain, Code2SessionResponse.class);

        // 初始化登录返回数据 并处理返回异常
        com.wash.shoes.domain.dy.model.Login.LoginResponse.Builder builder =
            com.wash.shoes.domain.dy.model.Login.LoginResponse.newBuilder();

        // 对返回数据异常处理
        if (response == null || response.getData() == null) {
            throw new WashException("数据异常");
        }
        if (response.getErrNo() != 0) {
            builder.setErrCode(-1);
            builder.setErrMsg(response.getErrTips());
            throw new WashException("数据异常");
        }
        // 返回成功则组装返回结构体
        builder.setErrCode(response.getErrNo());
        builder.setErrMsg("");
        builder.setErrCode(0);

        String token = Store.SetCache("", response.getData().getOpenid(), response.getData().getUnionId(), "",
            response.getData().getSessionKey());
        builder.setToken(token);

        log.info("dy log info is {} token is {}", JSONObject.toJSONString(response.getData()), token);

        builder.setOpenid(response.getData().getOpenid());
        builder.setUnionid(response.getData().getUnionId());

        // 添加抖音的用户信息,查询dy的用户信息
        CustomerPo customerPo = customerService.getByDyOpenId(builder.getOpenid());
        if (customerPo != null) {
            return R.ok(customerPo);
        }

        // 如果用户不存在,且没有传电话过来,就是说这个数据不对,需要重新注册
        if (StrUtil.isBlankIfStr(code2SessionRequest.getPhone())) {
            CustomerVo customerVo = new CustomerVo();
            customerVo.setSessionKey(response.getData().getSessionKey());
            return R.ok(customerVo);
        }
        // 绑定号码
        customerPo = customerService.getByPhone(code2SessionRequest.getPhone());
        if (customerPo != null) {
            // 设置抖音的openId
            customerPo.setDyOpenId(builder.getOpenid());
            customerPo.setDyUnionId(builder.getUnionid());
            customerService.updateById(customerPo);
            return R.ok(customerPo);
        }
        customerPo = new CustomerPo();
        customerPo.setDyOpenId(builder.getOpenid());
        customerPo.setDyUnionId(builder.getUnionid());
        customerPo.setPhone(code2SessionRequest.getPhone());
        customerPo.setName("抖音用户");
        customerService.saveOrUpdate(customerPo);
        return R.ok(customerPo);
    }

    @ApiOperation("获取用户的基本信息")
    @PostMapping(value = "/apps/getDyUserInfo", consumes = MediaType.APPLICATION_JSON_VALUE)
    public R<DyUserInfo> getDyUserInfo(@RequestBody EncryptedPhone encryptedPhone)
        throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException,
        NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
        // 请求体初始化pb结构
        // encryptedPhone.setSessionKey("kpNH+bcMUTUQ258rwjlDSw==");
        if (StrUtil.isBlank(encryptedPhone.getSessionKey())) {
            throw new WashException("sessionKey不能为空");
        }
        String decryptData = CbcCoding.decrypt(encryptedPhone.getEncryptedData(), encryptedPhone.getSessionKey(),
            encryptedPhone.getIv());
        log.info("getDyUserInfo is {}", decryptData);
        DyUserInfo dyUserInfo = JSONObject.parseObject(decryptData, DyUserInfo.class);
        return R.ok(dyUserInfo);
    }

    /**
     * 小程序利用code2session登录获取openid返回
     *
     * @return
     * @throws IOException
     */
    @ApiOperation("小程序利用code2session登录获取openid返回")
    @PostMapping(value = "/apps/loginNoPhone", consumes = MediaType.APPLICATION_JSON_VALUE)
    public R<CustomerPo> loginNoPhone(@RequestBody Code2SessionRequest code2SessionRequest) throws IOException {
        // 从请求头获取poId
        String poId = HeaderUtil.getPoId();
        if (StringUtils.isBlank(poId)) {
            throw new WashException("抖音门店id不能为空 数据异常");
        }
        // 根据poId查询门店
        LambdaQueryWrapper<ShopPo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopPo::getPoId, poId);
        ShopPo dbShopPo = shopService.getOne(queryWrapper);
        if (dbShopPo == null) {
            throw new WashException("抖音门店id不能找到店铺信息 数据异常");
        }
        Assert.notNull(dbShopPo.getBrandId(), "商铺:" + dbShopPo.getId() + ",品牌id不能为空");
        BrandPo brandPo = brandService.getById(dbShopPo.getBrandId());
        Assert.notNull(brandPo, "品牌信息未找到 数据异常");
        // 根据抖音请求的poId查找appId和appSecrete

        if (StringUtils.isBlank(brandPo.getAppid()) || StringUtils.isBlank(brandPo.getAppsecret())) {
            throw new WashException("根据门店信息未填写appId或secrete 数据异常");
        }

        // 请求体初始化pb结构
        code2SessionRequest.setAppid(brandPo.getAppid());
        code2SessionRequest.setSecret(brandPo.getAppsecret());
        code2SessionRequest.setAnonymousCode(null);
        // 正式地址：https://developer.toutiao.com/api/apps/v2/jscode2session
        // 沙盒地址：https://open-sandbox.douyin.com/api/apps/v2/jscode2session
        String domain = "developer.toutiao.com";
        if (dyProperty.getIsSandBox().equals("1")) {
            domain = "open-sandbox.douyin.com";
        }
        String code2SessionPath = "/api/apps/v2/jscode2session";
        Code2SessionResponse response = HttpUtil.HttpPost(code2SessionPath,
            JSONObject.toJSONString(code2SessionRequest), "https", domain, Code2SessionResponse.class);

        // 初始化登录返回数据 并处理返回异常
        com.wash.shoes.domain.dy.model.Login.LoginResponse.Builder builder =
            com.wash.shoes.domain.dy.model.Login.LoginResponse.newBuilder();

        // 对返回数据异常处理
        if (response == null || response.getData() == null) {
            throw new WashException("数据异常");
        }
        if (response.getErrNo() != 0) {
            builder.setErrCode(-1);
            builder.setErrMsg(response.getErrTips());
            throw new WashException("数据异常");
        }
        // 返回成功则组装返回结构体
        builder.setErrCode(response.getErrNo());
        builder.setErrMsg("");
        builder.setErrCode(0);

        String token = Store.SetCache("", response.getData().getOpenid(), response.getData().getUnionId(), "",
            response.getData().getSessionKey());
        builder.setToken(token);

        log.info("dy log info is {} token is {}", JSONObject.toJSONString(response.getData()), token);

        builder.setOpenid(response.getData().getOpenid());
        builder.setUnionid(response.getData().getUnionId());

        // 添加抖音的用户信息,查询dy的用户信息
        CustomerPo customerPo = customerService.getByDyOpenId(builder.getOpenid());
        if (customerPo != null) {
            return R.ok(customerPo);
        }

        customerPo = new CustomerPo();
        customerPo.setDyOpenId(builder.getOpenid());
        customerPo.setDyUnionId(builder.getUnionid());
        customerPo.setPhone(code2SessionRequest.getPhone());
        customerPo.setName("抖音用户");
        customerService.saveOrUpdate(customerPo);
        return R.ok(customerPo);
    }

}
